package com.stars.easyms.datasource;

import com.stars.easyms.base.constant.EasyMsCommonConstants;
import com.stars.easyms.datasource.common.EasyMsDataSourceConstant;
import com.stars.easyms.datasource.exception.IllegalDataSourceException;
import com.stars.easyms.datasource.holder.EasyMsMasterSlaveDataSourceHolder;
import com.stars.easyms.datasource.holder.EasyMsSynchronizationManager;
import lombok.Getter;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.sql.DataSource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <p>className: EasyMsMultiDataSource</p>
 * <p>description: EasyMs多数据源</p>
 *
 * @author guoguifang
 * @version 1.1.0
 * @date 2019-03-04 11:17
 */
public final class EasyMsMultiDataSource extends AbstractRoutingDataSource {

    @Getter
    private final Map<String, EasyMsMasterSlaveDataSource> dataSources = new ConcurrentHashMap<>(32);

    @Override
    protected DataSource determineDataSource() {
        if (CollectionUtils.isEmpty(this.dataSources)) {
            throw new IllegalDataSourceException("There is no valid datasource!");
        }
        DataSource dataSource = EasyMsSynchronizationManager.getEasyMsDataSource();
        if (dataSource == null) {
            dataSource = EasyMsMasterSlaveDataSourceHolder.getMasterSlaveDataSource();
            if (dataSource == null) {
                return getDefaultDataSource();
            }
        }
        return dataSource;
    }

    public EasyMsMasterSlaveDataSource getDataSource(String dataSourceName) {
        Assert.notNull(dataSourceName, "The argument dataSourceName is null!");
        EasyMsMasterSlaveDataSource dataSource = this.dataSources.get(dataSourceName);
        if(dataSource == null) {
            throw new IllegalDataSourceException("Cannot determine DataSource for dataSourceName [{}]",
                    EasyMsDataSourceConstant.DEFAULT_DATASOURCE_NAME.equals(dataSourceName) ? EasyMsCommonConstants.DEFAULT : dataSourceName);
        }
        return dataSource;
    }

    public EasyMsDataSource getCurrentDataSource() {
        return (EasyMsDataSource) ((EasyMsMasterSlaveDataSource) determineDataSource()).determineDataSource();
    }

    public EasyMsMasterSlaveDataSource getDefaultDataSource() {
        return getDataSource(EasyMsDataSourceConstant.DEFAULT_DATASOURCE_NAME);
    }

    void addDataSources(String dataSourceName, EasyMsMasterSlaveDataSource easyMsMasterSlaveDataSource) {
        Assert.notNull(dataSourceName, "The argument dataSourceName is null!");
        Assert.notNull(easyMsMasterSlaveDataSource, "The argument easyMsMasterSlaveDataSource is null!");
        if (easyMsMasterSlaveDataSource.getMasterDataSourceSet().isEmpty() && easyMsMasterSlaveDataSource.getSlaveDataSourceSet().isEmpty()) {
            throw new IllegalDataSourceException("The masterSlaveDatasource '{}' has not valid datasource!", dataSourceName);
        }
        EasyMsMasterSlaveDataSource oldEasyMsMasterSlaveDataSource = this.dataSources.get(dataSourceName);
        if (oldEasyMsMasterSlaveDataSource == null) {
            this.dataSources.put(dataSourceName, easyMsMasterSlaveDataSource);
        } else {
            oldEasyMsMasterSlaveDataSource.getMasterDataSourceSet().addAllEasyMsDataSources(easyMsMasterSlaveDataSource.getMasterDataSourceSet());
            oldEasyMsMasterSlaveDataSource.getSlaveDataSourceSet().addAllEasyMsDataSources(easyMsMasterSlaveDataSource.getSlaveDataSourceSet());
        }
    }

    EasyMsMultiDataSource() {}
}